/**
 * https://www.bilibili.com/video/BV1Mb411e7re?p=33
 * 直流电机介绍
 *  直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极，当电极正接时，电机正转，当电极反接时，电机反转
 *  直流电机主要由永磁体（定子）、线圈（转子）和换向器组成
 *  除"直流电机"外，常见的电机还有"步进电机"、"舵机"、"无刷电机"、"空心杯电机"等
 * 
 * 电机驱动电路:
 *  大功率器件直接驱动
 *  H桥驱动
 * 
 * PWM介绍:
 *  PWM（Pulse Width Modulation）即脉冲宽度调制，在具有惯性的系统中，可以通过对一系列脉冲的宽度进行调制，来等效地获得所需要的模拟参量，常应用于电机控速、开关电源等领域
 *  PWM重要参数：
 *      频率 = 1 / TS       占空比 = TON / TS       精度 = 占空比变化步距
 * 
 * https://www.bilibili.com/video/BV1Mb411e7re?p=34
 * 有些 MCU 有产生 PWM 的功能
 * 
 * 产生PWM方法:
 *  模型结构
 *  波形
 */
#include <REGX52.H>
#include "Link/Delay_Utils.h"
#include "Link/Single_Keyboard_Utils.h"
#include "Link/Timer0_Utils.h"
#include "Link/Motor_Utils.h"

void Breathe_Light();
static void Timer0_onTick();

//灯/电机端口
sbit Motor_Port = P1^0;

void main_motor() {
    //                       转速   对比值(值越大, 灯越亮/电机越快)
    unsigned char keyNumber, Speed, Compare;

    //1.呼吸灯
    // Breathe_Light();

    /**
     * 2.直流电机调速(10KHz~20KHz, 频率低了电机会抖动, 高了占用CPU资源.)
     * 100us溢出1次, 1秒溢出10K次
     */
    Timer0_Init(100, 0);
    Timer0_setOnTickListener_Exact(1, &Timer0_onTick);

    while (1) {
        keyNumber = Single_Keyboard_Down_Timer_Get();
        if (keyNumber == 1) {
            Speed++;
            Speed %= 4;
            if(Speed == 0) { Compare = 0; }    //设置比较值，改变PWM占空比
            else if(Speed == 1) { Compare = 50; }
            else if(Speed == 2) { Compare = 75; }
            else { Compare = 100; }
            //设置速度
            Motor_SetSpeed(Compare);
        }
    }
}

static void Delay(unsigned int t) {
    while (t--);
}
/**
 * 1.呼吸灯
 */
static void Breathe_Light() {
    unsigned int lightTime, lightTotalTime = 200;
    while (1) {
        //亮度逐渐降低
        for (lightTime = 0; lightTime < lightTotalTime; lightTime++) {
            Motor_Port = 0;
            Delay(lightTime);
            Motor_Port = 1;
            Delay(lightTotalTime - lightTime);
        }
        //亮度逐渐升高
        for (lightTime = lightTotalTime; lightTime > 0; lightTime--) {
            Motor_Port = 0;
            Delay(lightTime);
            Motor_Port = 1;
            Delay(lightTotalTime - lightTime);
        }
    }
}

static void Timer0_onTick() {
    static unsigned char T0Counter = 0;
    //100μs调用1次
    Motor_CallOnTimer();

    //键盘, 15us扫描1次
    T0Counter++;
    if (T0Counter >= 150) {
        T0Counter = 0;
        Single_Keyboard_Down_Timer(1);
    }
}
